package com.incito.crawl.common.httpclient;

import com.incito.crawl.common.utils.http.CrawlHttpClientConfig;
import com.incito.crawl.common.utils.http.CrawlerKit;
import com.incito.crawl.common.utils.proxy.ProxyInfo;
import com.incito.crawl.common.utils.proxy.ProxyKit;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpRequestWrapper;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.conn.DefaultRoutePlanner;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: liu
 * Date: 14-6-6
 * Time: 下午2:36
 * To change this template use File | Settings | File Templates.
 */
public class ProxyRoutePlanner extends DefaultRoutePlanner {

    private static Logger logger = LoggerFactory.getLogger("crawldesc");

    public ProxyRoutePlanner() {
        super(null);
    }

    @Override
    protected HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
        ProxyInfo proxyInfo = null;
        boolean useProxy = true;
        HttpHost proxy = null;
        CrawlHttpClientContext crawlHttpClientContext = null;

        HttpRequestWrapper requestWrapper = (HttpRequestWrapper) request;

        if (context instanceof CrawlHttpClientContext) {
            crawlHttpClientContext = (CrawlHttpClientContext) context;
            useProxy = crawlHttpClientContext.getUseProxy();
        }

        if (useProxy) {

            if (crawlHttpClientContext != null && crawlHttpClientContext.getUseProxyInfo() && crawlHttpClientContext.getProxyInfo() != null) {
                proxyInfo = crawlHttpClientContext.getProxyInfo();
            }
            else if (context instanceof HttpClientContext) {
                HttpClientContext httpClientContext = (HttpClientContext) context;
                List<URI> redirectLocations = httpClientContext.getRedirectLocations();
                if (redirectLocations != null && redirectLocations.size() > 0) {
                    HttpRequestBase httpRequestBase = (HttpRequestBase) ((HttpRequestWrapper) request).getOriginal();
                    RequestConfig oldRequestConfig = httpRequestBase.getConfig();
                    if (oldRequestConfig != null && oldRequestConfig.getConnectTimeout() == 1000
                            && oldRequestConfig.getSocketTimeout() == 5000) {
                        //do nothing
                    } else {
                        RequestConfig requestConfig = CrawlerKit.createRequestConfigBuilder(true, 1000, 5000, 15).build();
                        httpRequestBase.setConfig(requestConfig);
                    }

//                    proxy = getProxyFromXForwardForHeader(requestWrapper);
                }
                HttpRoute proxyRoute = (HttpRoute) httpClientContext.getHttpRoute();
                Integer proxyUseCount = (Integer) httpClientContext.getAttribute(CrawlHttpClientConfig.PROXY_USE_COUNT);
                if (proxyUseCount == null) {
                    proxyUseCount = 0;
                }

                if (proxyRoute != null) {
                    if (proxyUseCount < 100) {

                        proxy = proxyRoute.getProxyHost();
                        proxyUseCount++;
                        httpClientContext.setAttribute(CrawlHttpClientConfig.PROXY_USE_COUNT, proxyUseCount);
                    }

                }
            }

            try {
                if (proxy == null) {
                    if (proxyInfo == null) {
                        if (crawlHttpClientContext != null && crawlHttpClientContext.getProxyRuleName() != null) {
                            proxyInfo = ProxyKit.getProxy(crawlHttpClientContext.getProxyRuleName());
                        } else {
                            proxyInfo = ProxyKit.getProxy();
                        }
                    }
                    if (proxyInfo != null) {
                        logger.info("getProxy-ip:{},port:{}", proxyInfo.getIp(), proxyInfo.getPort());
                        proxy = new HttpHost(proxyInfo.getIp(), proxyInfo.getPort());
                        requestWrapper.getOriginal().setHeader("X-Forwarded-For", proxy.toHostString());
                    }
                }

                logger.info("proxy=" + proxy);
                return proxy;
            } catch (Exception e) {
                logger.error("设置抓取代理出错", e);
            }
        }

        return super.determineProxy(target, request, context);
    }

    private HttpHost getProxyFromXForwardForHeader(HttpRequestWrapper requestWrapper) {
        HttpHost proxy = null;

        Header proxyHeader = requestWrapper.getOriginal().getFirstHeader("X-Forwarded-For");
        if (proxyHeader != null) {
            String proxyHeaderValue = proxyHeader.getValue();
            if (StringUtils.isNotEmpty(proxyHeaderValue)) {
                String[] proxyHostPair = proxyHeaderValue.split(":");
                String proxyHost = proxyHostPair[0];
                String proxyPort = proxyHostPair[1];
                int proxyPortNum = Integer.parseInt(proxyPort);

                proxy = new HttpHost(proxyHost, proxyPortNum);
            }
        }
        return proxy;
    }
}
